﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using LunwenYun.Portal.WebLogic;
using LunwenYun.Infrastructure.Entities.Enum;
using LunwenYun.Infrastructure.Entities.Entity;
using LunwenYun.Tool.Framework;
using LunwenYun.Portal.Web.Models;
using LunwenYun.Portal.Biz.TenpayLib;
using System.Collections;
using System.Text;
using LunwenYun.Portal.Biz;

namespace LunwenYun.Portal.Web.Controllers
{
    public class PayController : Controller
    {
        //
        // GET: /Pay/

        [Auth(UserRole.Member)]
        public ActionResult choose(int trade,string token)
        {
            token = EncodeByBase64.Decode(token);
            var o = new Trade().Find(trade.ToString());
            if (o == null || o.Consumer != HttpContext.User.Identity.Name)
            {
                return Redirect("/m/payfail/" + 0);
            }
            if (o.Consumer.ToLower() != HttpContext.User.Identity.Name.ToLower() ||
                o.IsDelete)
            { 
                return Redirect("/m/payfail/" + 1);
            }
            if (o.Token != token || o.Status != TradeStatus.WaitPay)
            {
                return Redirect("/m/payfail/" + 2);
            }
            ViewBag.TradeEntity = o;
            ViewBag.Provider = new User().Find(o.Supplier);
            ViewBag.Trade = trade;
            ViewBag.Token = token;
            return View();
        }
        [HttpPost]
        [Auth(UserRole.Member)]
        public ActionResult doPay(int trade,string token, int bank_type_value)
        {
            var o = new Trade().Find(trade.ToString());
            if (o == null)
            {
                return Redirect("/m/payfail/" + 0);
            }
            if (o.Consumer.ToLower() != HttpContext.User.Identity.Name.ToLower() ||
                o.IsDelete)
            {
                return Redirect("/m/payfail/" + 1);
            }
            if (o.Token != token || o.Status != TradeStatus.WaitPay)
            {
                return Redirect("/m/payfail/" + 2);
            }
            return RedirectToAction("Exchange", new
            {
                token = EncodeByBase64.Encode(new DoPayModel() { TradeId = trade, BankType = bank_type_value }.ToJson())
            });
        }
        [Auth(UserRole.Member)]
        public ActionResult Exchange(string token)
        {
            DoPayModel model = EncodeByBase64.Decode(token).ToObject<DoPayModel>();
            if (model == null)
            {
                return Redirect("/m/payfail/" + 0);
            }
            var trade = new Trade().Find(model.TradeId.ToString());
            if (trade != null)
            {
                PayLog payLog = new PayLog().Find(c => c.TradeId == trade.Id);
                if (payLog == null)
                {
                    payLog = new PayLog()
                    {
                        TradeId = model.TradeId,
                        PayDate = DateTime.Now,
                        PayNo = PayLog.PayNoGenerator(model.TradeId),
                        PayStatus = 1,
                        Price = trade.Momey
                    }.PostAdd();
                }
                else
                {
                    if (payLog.PayStatus != 2)
                    {
                        payLog.TradeId = model.TradeId;
                        payLog.PayDate = DateTime.Now;
                        payLog.Price = trade.Momey;
                        payLog.PostModify();
                    }
                }
                if (payLog != null && payLog.PayStatus == 1)
                {
                    RequestHandler reqHandler = new RequestHandler(System.Web.HttpContext.Current);
                    //初始化
                    reqHandler.init();
                    //设置密钥
                    reqHandler.setKey(TenpayUtil.tenpay_key);
                    reqHandler.setGateUrl("https://gw.tenpay.com/gateway/pay.htm");

                    //-----------------------------
                    //设置支付参数
                    //-----------------------------
                    reqHandler.setParameter("partner", TenpayUtil.bargainor_id);		        //商户号
                    reqHandler.setParameter("out_trade_no", payLog.PayNo);		//商家订单号
                    reqHandler.setParameter("total_fee",
                        ((int)(trade.Momey * 100)).ToString());			        //商品金额,以分为单位
                    reqHandler.setParameter("return_url", TenpayUtil.tenpay_return);		    //交易完成后跳转的URL
                    reqHandler.setParameter("notify_url", TenpayUtil.tenpay_notify);		    //接收财付通通知的URL
                    reqHandler.setParameter("body", "学术论文云平台约稿费");	                    //商品描述
                    reqHandler.setParameter("bank_type", model.BankType == 0 ? "DEFAULT" : model.BankType.ToString());		    //银行类型(中介担保时此参数无效)
                    reqHandler.setParameter("spbill_create_ip", TenpayUtil.ip);   //用户的公网ip，不是商户服务器IP
                    reqHandler.setParameter("fee_type", "1");                    //币种，1人民币
                    reqHandler.setParameter("subject", "学术论文云平台约稿费");              //商品名称(中介交易时必填)


                    //系统可选参数
                    reqHandler.setParameter("sign_type", "MD5");
                    reqHandler.setParameter("service_version", "1.0");
                    reqHandler.setParameter("input_charset", "UTF-8");
                    reqHandler.setParameter("sign_key_index", "1");

                    //业务可选参数

                    reqHandler.setParameter("attach", EncodeByBase64.Encode(new PayExchangeModel()
                    {
                        PayId=payLog.Id,
                        Price=payLog.Price,
                        ToDate=DateTime.Now.ToString(),
                        TradeId=trade.Id
                    }.ToJson()));    //附加数据，原样返回             
                    reqHandler.setParameter("product_fee", 
                        ((int)(trade.Momey * 100)).ToString());                  //商品费用，必须保证transport_fee + product_fee=total_fee
                    reqHandler.setParameter("transport_fee", "0");               //物流费用，必须保证transport_fee + product_fee=total_fee
                    reqHandler.setParameter("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));            //订单生成时间，格式为yyyymmddhhmmss
                    reqHandler.setParameter("time_expire", "");                 //订单失效时间，格式为yyyymmddhhmmss
                    reqHandler.setParameter("buyer_id", "");                    //买方财付通账号
                    reqHandler.setParameter("goods_tag", "");                   //商品标记
                    reqHandler.setParameter("trade_mode", "1");                 //交易模式，1即时到账(默认)，2中介担保，3后台选择（买家进支付中心列表选择）
                    reqHandler.setParameter("transport_desc", "");              //物流说明
                    reqHandler.setParameter("trans_type", "2");                  //交易类型，1实物交易，2虚拟交易
                    reqHandler.setParameter("agentid", "");                     //平台ID
                    reqHandler.setParameter("agent_type", "");                  //代理模式，0无代理(默认)，1表示卡易售模式，2表示网店模式
                    reqHandler.setParameter("seller_id", "");                   //卖家商户号，为空则等同于partner



                    //获取请求带参数的url
                    string requestUrl = reqHandler.getRequestURL();
                    StringBuilder html = new StringBuilder();
                    html.Append("<form id=\"payform\" method=\"post\" action=\"" + reqHandler.getGateUrl() + "\" >\n");
                    Hashtable ht = reqHandler.getAllParameters();
                    foreach (DictionaryEntry de in ht)
                    {
                        html.Append("<input type=\"hidden\" name=\"" + de.Key + "\" value=\"" + de.Value + "\" >\n");
                    }
                    html.Append("\n</form>\n");
                    ViewBag.HTML = html.ToString();
                    LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "发起支付：\r\n" + html.ToString());
                    return View();
                }
                else
                {
                    return Redirect("/m/payfail/" + 0);
                }
            }
            else
            {
                return Redirect("/m/payfail/" + 0);
            }
        }
        [Auth(UserRole.Member)]
        public ActionResult payreturn()
        {
            ResponseHandler resHandler = new ResponseHandler(System.Web.HttpContext.Current);
            resHandler.setKey(TenpayUtil.tenpay_key);
            resHandler.LogParameter("支付返回，\r\n");
            if (resHandler.isTenpaySign())
            {
                ///通知id
                string notify_id = resHandler.getParameter("notify_id");

                RequestHandler queryReq = new RequestHandler(System.Web.HttpContext.Current);
                queryReq.init();
                queryReq.setKey(TenpayUtil.tenpay_key);
                queryReq.setGateUrl("https://gw.tenpay.com/gateway/simpleverifynotifyid.xml");
                queryReq.setParameter("partner", TenpayUtil.bargainor_id);
                queryReq.setParameter("notify_id", notify_id);

                //通信对象
                TenpayHttpClient httpClient = new TenpayHttpClient();
                httpClient.setTimeOut(5);
                //设置请求内容
                httpClient.setReqContent(queryReq.getRequestURL());
                //后台调用
                if (httpClient.call())
                {
                    //设置结果参数
                    ClientResponseHandler queryRes = new ClientResponseHandler();
                    queryRes.setContent(httpClient.getResContent());
                    queryRes.setKey(TenpayUtil.tenpay_key);
                    //判断签名及结果
                    //只有签名正确,retcode为0，trade_state为0才是支付成功
                    if (queryRes.isTenpaySign())
                    {
                        //商户订单号
                        string out_trade_no = resHandler.getParameter("out_trade_no");
                        //财付通订单号
                        string transaction_id = resHandler.getParameter("transaction_id");
                        //金额,以分为单位
                        string total_fee = resHandler.getParameter("total_fee");
                        //如果有使用折扣券，discount有值，total_fee+discount=原请求的total_fee
                        string discount = resHandler.getParameter("discount");
                        //支付结果
                        string trade_state = resHandler.getParameter("trade_state");
                        //交易模式，1即时到账，2中介担保
                        string trade_mode = resHandler.getParameter("trade_mode");


                        if ("0".Equals(queryRes.getParameter("retcode")))
                        {
                            string attach = resHandler.getParameter("attach");
                            PayExchangeModel exchangeModel = null;
                            if (!String.IsNullOrEmpty(attach))
                            {
                                string decodeAttach = EncodeByBase64.Decode(attach);
                                if (!String.IsNullOrEmpty(decodeAttach))
                                {
                                    LogHelper.Write(CommonLogger.Pay, LogLevel.Info, decodeAttach);
                                    exchangeModel = decodeAttach.ToObject<PayExchangeModel>();
                                    if (exchangeModel == null)
                                    {
                                        LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，反序列化失败：" + decodeAttach);
                                    }
                                }
                                else
                                {
                                    LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，Attach 解码失败");
                                }
                            }
                            else
                            {
                                LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，A返回字符串缺少 Attach");
                            }
                            //判断签名及结果
                            if ("1".Equals(trade_mode) && "0".Equals(trade_state))
                            {
                                //即时到账 
                                //------------------------------
                                //即时到账处理业务开始
                                //------------------------------
                                if (exchangeModel != null)
                                {
                                    var pay = new PayLog().Find(exchangeModel.PayId.ToString());
                                    var trade = new Trade().Find(exchangeModel.TradeId.ToString());
                                    if (pay == null || trade == null)
                                    {
                                        ViewBag.PayResult = false;
                                        ViewBag.Message = "支付详情校验失败";
                                        LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，pay || trade 查询为null");
                                    }
                                    else
                                    {
                                        if (Int32.Parse(total_fee) == trade.Momey * 100)
                                        {
                                            if (pay.PayStatus == 1)
                                            {
                                                pay.PayStatus = 2;
                                                pay.PayBackDate = DateTime.Now;
                                                pay.PayBackString = resHandler.getAllPatameter().ToJson();
                                                if (pay.PostModify() == null)
                                                {
                                                    LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，pay 更新失败！ payId:" + pay.Id);
                                                }
                                            }
                                            if (trade.Status == TradeStatus.WaitPay)
                                            {
                                                new TradeHistory()
                                                {
                                                    NxtStatus=TradeStatus.Pay,
                                                    Operator="pay",
                                                    PreStatus= trade.Status,
                                                    RecordDate=DateTime.Now,
                                                    Remark = "支付返回：payreturn",
                                                    TradeId=trade.Id
                                                }.PostAdd();

                                                trade.Status = TradeStatus.Pay;
                                                trade.Token = AesAlgorithm.Encrypt(Guid.NewGuid().ToString());
                                                if (trade.PostModify() == null)
                                                {
                                                    LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，trade 更新失败！ tradeId:" + trade.Id);
                                                }
                                            }
                                            
                                            ViewBag.Trade = trade;
                                            ViewBag.Article = new Article().Find(trade.ArticleId.ToString());
                                            ViewBag.Provider = new User().Find(trade.Supplier);
                                            ViewBag.PayResult = true;
                                        }
                                        else
                                        {
                                            ViewBag.PayResult = false;
                                            ViewBag.Message = "支付详情校验失败";
                                        }
                                    }
                                }
                                else
                                {
                                    ViewBag.PayResult = false;
                                    ViewBag.Message = "支付详情校验失败";
                                }

                            }
                            else
                            {
                                ViewBag.PayResult = false;
                                ViewBag.Message = "支付失败，系统异常";
                            }
                        }
                        else
                        {
                            ViewBag.PayResult = false;
                            ViewBag.Message = "非法支付数据！";
                        }
                    }
                    else
                    {
                        ViewBag.PayResult = false;
                        ViewBag.Message = "签名验证失败，支付确认失败！";
                    }
                }
                else
                {
                    ViewBag.PayResult = false;
                    ViewBag.Message = "支付失败，系统异常";
                }
            }
            else
            {
                ViewBag.PayResult = false;
                ViewBag.Message = "签名验证失败，支付确认失败！";
            }
            return View();
        }
        
        public void paynotify()
        {
            LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "收到通知");
            ResponseHandler resHandler = new ResponseHandler(System.Web.HttpContext.Current);
            resHandler.setKey(TenpayUtil.tenpay_key);
            resHandler.LogParameter("支付通知，\r\n");
            if (resHandler.isTenpaySign())
            {
                ///通知id
                string notify_id = resHandler.getParameter("notify_id");

                RequestHandler queryReq = new RequestHandler(System.Web.HttpContext.Current);
                queryReq.init();
                queryReq.setKey(TenpayUtil.tenpay_key);
                queryReq.setGateUrl("https://gw.tenpay.com/gateway/simpleverifynotifyid.xml");
                queryReq.setParameter("partner", TenpayUtil.bargainor_id);
                queryReq.setParameter("notify_id", notify_id);

                //通信对象
                TenpayHttpClient httpClient = new TenpayHttpClient();
                httpClient.setTimeOut(5);
                //设置请求内容
                httpClient.setReqContent(queryReq.getRequestURL());
                //后台调用
                if (httpClient.call())
                {
                    //设置结果参数
                    ClientResponseHandler queryRes = new ClientResponseHandler();
                    queryRes.setContent(httpClient.getResContent());
                    queryRes.setKey(TenpayUtil.tenpay_key);
                    //判断签名及结果
                    //只有签名正确,retcode为0，trade_state为0才是支付成功
                    if (queryRes.isTenpaySign())
                    {
                        //商户订单号
                        string out_trade_no = resHandler.getParameter("out_trade_no");
                        //财付通订单号
                        string transaction_id = resHandler.getParameter("transaction_id");
                        //金额,以分为单位
                        string total_fee = resHandler.getParameter("total_fee");
                        //如果有使用折扣券，discount有值，total_fee+discount=原请求的total_fee
                        string discount = resHandler.getParameter("discount");
                        //支付结果
                        string trade_state = resHandler.getParameter("trade_state");
                        //交易模式，1即时到账，2中介担保
                        string trade_mode = resHandler.getParameter("trade_mode");


                        if ("0".Equals(queryRes.getParameter("retcode")))
                        {
                            string attach = resHandler.getParameter("attach");
                            PayExchangeModel exchangeModel = null;
                            if (!String.IsNullOrEmpty(attach))
                            {
                                string decodeAttach = EncodeByBase64.Decode(attach);
                                if (!String.IsNullOrEmpty(decodeAttach))
                                {
                                    LogHelper.Write(CommonLogger.Pay, LogLevel.Info, decodeAttach);
                                    exchangeModel = decodeAttach.ToObject<PayExchangeModel>();
                                    if (exchangeModel == null)
                                    {
                                        LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，反序列化失败：" + decodeAttach);
                                    }
                                }
                                else
                                {
                                    LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，Attach 解码失败");
                                }
                            }
                            else
                            {
                                LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，A返回字符串缺少 Attach");
                            }
                            //判断签名及结果
                            if ("1".Equals(trade_mode) && "0".Equals(trade_state))
                            {
                                //即时到账 
                                //------------------------------
                                //即时到账处理业务开始
                                //------------------------------
                                if (exchangeModel != null)
                                {
                                    var pay = new PayLog().Find(exchangeModel.PayId.ToString());
                                    var trade = new Trade().Find(exchangeModel.TradeId.ToString());
                                    if (pay == null || trade == null)
                                    {
                                        LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付通知，pay || trade 查询为null");
                                    }
                                    else
                                    {
                                        if (Int32.Parse(total_fee) == trade.Momey * 100)
                                        {
                                            if (pay.PayStatus == 1)
                                            {
                                                pay.PayStatus = 2;
                                                pay.PayBackDate = DateTime.Now;
                                                pay.PayBackString = resHandler.getAllPatameter().ToJson();
                                                if (pay.PostModify() == null)
                                                {
                                                    LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，pay 更新失败！ payId:" + pay.Id);
                                                }
                                            }
                                            if (trade.Status == TradeStatus.WaitPay)
                                            {
                                                new TradeHistory()
                                                {
                                                    NxtStatus = TradeStatus.Pay,
                                                    Operator = "pay",
                                                    PreStatus = trade.Status,
                                                    RecordDate = DateTime.Now,
                                                    Remark = "支付通知：paynotify",
                                                    TradeId = trade.Id
                                                }.PostAdd();

                                                trade.Status = TradeStatus.Pay;
                                                trade.Token = AesAlgorithm.Encrypt(Guid.NewGuid().ToString());
                                                if (trade.PostModify() == null)
                                                {
                                                    LogHelper.Write(CommonLogger.Pay, LogLevel.Info, "支付返回，trade 更新失败！ tradeId:" + trade.Id);
                                                }
                                            }
                                            
                                            Response.Write("Success");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}